package com.example.demo22_csrf1.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.LazyCsrfTokenRepository;

/**
 * csrf 攻击是黑客通过 浏览器自动携带 cookie 信息造成的，比如：当你登录银行网站后，新开一个窗口打开危险网站，在危险网站点击了一个链接
 * 如果该链接会访问你登录的银行网站进行转账，而之前你在浏览器已经登录的该网站，那么会自动带上 cookie，从而造成转账成功，导致钱财损失。
 *
 * 解决办法：
 *      csrf 攻击不关心 cookie 中的信息，只是利用浏览器自动携带 cookie，从而制造攻击
 *      所以我们只需要登录后获取一个随机参数，如何提交请求时传递过去，就可以解决问题
 *
 * security 默认开启了 csrf 防御，默认是前后端不分离将 csrf 随机参数保存到 session 中
 *      当请求过来时，判断能否从 session 加载出 csrf token，第一次请求不能加载，就会生成新的 csrf token
 *      并判断请求方法是否需要进行校验，如果需要校验就判断从 session 取出来的 csrf 和 表单参数传过来的 csrf 是否相等，如果不相等就拦截
 * 除了默认策略还有
 * 1. CookieCsrfTokenRepository
 *      用于前后端分离的策略，将 csrf 随机参数保存到 cookie 中，前端从 cookie 中取出来然后放在请求参数或者请求头中传递给后端
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and().formLogin()
                .loginPage("/login.html")
                .successHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write("登录成功");
                })
                .permitAll()
                .and().csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}
